<!DOCTYPE html>
<html lang="en-us">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>使用dplyr进行数据转换 | Record life to a data scientist</title>
    <link rel="stylesheet" href="/css/style.css" />
    <link rel="stylesheet" href="/css/fonts.css" />
    <link href="//cdn.bootcss.com/highlight.js/9.12.0/styles/github.min.css" rel="stylesheet">
  </head>

  <body>
    <nav>
    <ul class="menu">
      
      <li><a href="/">Home</a></li>
      
      <li><a href="/about/">About</a></li>
      
      <li><a href="/categories/">Categories</a></li>
      
      <li><a href="/tags/">Tags</a></li>
      
      <li><a href="/index.xml">Subscribe</a></li>
      
    </ul>
    <hr/>
    </nav>

<div class="article-meta">
<h1><span class="title">使用dplyr进行数据转换</span></h1>
<h2 class="author">王诗翔</h2>
<h2 class="date">2018/03/21</h2>
<p class="terms">
  
  
  Categories: <a href="/categories/r">R</a> <a href="/categories/%E6%95%B0%E6%8D%AE%E5%88%86%E6%9E%90">数据分析</a> 
  
  
  
  Tags: <a href="/tags/notebook">notebook</a> <a href="/tags/dplyr">dplyr</a> 
  
  
</p>
</div>

<main>
<div id="TOC">
<ul>
<li><a>准备</a><ul>
<li><a href="#nycflights13">nycflights13</a></li>
<li><a href="#dplyr">dplyr基础</a></li>
</ul></li>
<li><a href="#filter">使用filter()过滤行</a><ul>
<li><a>比较</a></li>
<li><a>逻辑操作符</a></li>
<li><a>缺失值</a></li>
<li><a>练习</a></li>
</ul></li>
<li><a href="#arrange">使用arrange()排列行</a><ul>
<li><a href="#-1">练习</a></li>
</ul></li>
<li><a href="#select">使用select()选择列</a><ul>
<li><a href="#-2">练习</a></li>
</ul></li>
<li><a href="#mutate">使用mutate()添加新变量</a><ul>
<li><a>有用的创造函数</a></li>
</ul></li>
<li><a href="#summarize">使用summarize()计算汇总值</a></li>
<li><a>使用管道整合多个操作</a><ul>
<li><a href="#-1">缺失值</a></li>
<li><a>计数</a></li>
<li><a>有用的汇总函数</a></li>
<li><a href="#mutates">分组的Mutates</a></li>
</ul></li>
</ul>
</div>

<p>该部分学习内容来自《R for Data Science》。</p>
<p>在对数据进行可视化之前我们往往需要进行数据转换以得到可视化所需要的数据内容与格式。这里我们使用<code>dplyr</code>包操作2013年纽约市的航班起飞数据集（2013）。</p>
<section class="level2">
<h2>准备</h2>
<p>这部分我们聚焦于如何使用<code>dplyr</code>包，除<code>ggplot2</code>的另一个<strong>tidyverse</strong>核心成员。我们将使用<code>nyclights13</code>数据包解释关键的概念并使用<code>ggplot2</code>帮助理解数据。</p>
<pre class="r"><code># 导入包
library(nycflights13) # 请确保在使用前已经安装好这些包
library(tidyverse)
## -- Attaching packages ----------------------------- tidyverse 1.2.1 --
## √ ggplot2 2.2.1     √ purrr   0.2.4
## √ tibble  1.4.1     √ dplyr   0.7.4
## √ tidyr   0.7.2     √ stringr 1.2.0
## √ readr   1.1.1     √ forcats 0.2.0
## -- Conflicts -------------------------------- tidyverse_conflicts() --
## x dplyr::filter() masks stats::filter()
## x dplyr::lag()    masks stats::lag()</code></pre>
<p>注意一下你导入<code>tidyverse</code>包时给出的冲突信息（Conflicts），它告诉你<strong>dplyr</strong>覆盖了R基础包中的函数。<strong>如果你想要在载入<code>tidyverse</code>包后仍然使用这些函数，你需要使用函数的全名<code>stats::filter()</code>和<code>stats::lag()</code>进行调用。</strong></p>
<section id="nycflights13" class="level3">
<h3>nycflights13</h3>
<p>我们将使用<code>nycflights13::flights</code>来探索<code>dplyr</code>包基本的数据操作<strong>动词</strong>。该数据集包含2013年336,776次航班起飞数据，来自美国交通统计局。</p>
<pre class="r"><code>flights
## # A tibble: 336,776 x 19
##     year month   day dep_time sched_dep_time dep_delay arr_time
##    &lt;int&gt; &lt;int&gt; &lt;int&gt;    &lt;int&gt;          &lt;int&gt;     &lt;dbl&gt;    &lt;int&gt;
##  1  2013     1     1      517            515      2.00      830
##  2  2013     1     1      533            529      4.00      850
##  3  2013     1     1      542            540      2.00      923
##  4  2013     1     1      544            545     -1.00     1004
##  5  2013     1     1      554            600     -6.00      812
##  6  2013     1     1      554            558     -4.00      740
##  7  2013     1     1      555            600     -5.00      913
##  8  2013     1     1      557            600     -3.00      709
##  9  2013     1     1      557            600     -3.00      838
## 10  2013     1     1      558            600     -2.00      753
## # ... with 336,766 more rows, and 12 more variables: sched_arr_time &lt;int&gt;,
## #   arr_delay &lt;dbl&gt;, carrier &lt;chr&gt;, flight &lt;int&gt;, tailnum &lt;chr&gt;,
## #   origin &lt;chr&gt;, dest &lt;chr&gt;, air_time &lt;dbl&gt;, distance &lt;dbl&gt;, hour &lt;dbl&gt;,
## #   minute &lt;dbl&gt;, time_hour &lt;dttm&gt;</code></pre>
<p>与基本包显示的普通数据集输出不同，这里适配地显示了在一个屏幕前几行和所有的列（我们可以使用<code>View(flights）</code>在Rstudio中查看数据集的所有信息。输出显示不同的原因是这个数据集是一个<em>Tibble</em>。<strong>Tibbles</strong>都是数据框<code>data.frame</code>，但经过改良以便于更好（在<code>tidyverse</code>生态中）工作。现在我们不必纠结于这些差异，在后续内容中我们会进行学习。</p>
<p>你可能已经注意到每个列名下面有<strong>三到四个字母的缩写</strong>。它们描述了每个变量的类型：</p>
<ul>
<li><code>int</code>代表整数</li>
<li><code>dbl</code>代表浮点数或者实数</li>
<li><code>chr</code>代表字符向量或者字符串</li>
<li><code>dttm</code>代表日期-时间</li>
</ul>
<p>还有其他三种数据类型在本部分不会使用到，但后续我们会接触：</p>
<ul>
<li><code>lgl</code>代表逻辑向量，只含<code>TRUE</code>和<code>FALSE</code></li>
<li><code>fctr</code>代表因子，R用它来代表含固定可能值的分类变量</li>
<li><code>date</code>代表日期</li>
</ul>
</section>
<section id="dplyr" class="level3">
<h3>dplyr基础</h3>
<p>这部分我们学习5个关键的<code>dplyr</code>函数，它可以让我们解决遇到的大部分数据操作问题：</p>
<ul>
<li>根据值选择观察（记录），<code>filter()</code></li>
<li>对行重新排序，<code>arrange()</code></li>
<li>根据名字选择变量，<code>select()</code></li>
<li>根据已知的变量创建新的变量，<code>mutate()</code></li>
<li>将许多值塌缩为单个描述性汇总，<code>summarize()</code></li>
</ul>
<p>这些函数都可以通过<code>group_by()</code>衔接起来，该函数改变上述每个函数的作用域，<strong>从操作整个数据集到按组与组操作</strong>。这六个函数提供了数据操作语言的动词。</p>
<p>所有的动词工作都非常相似：</p>
<ol type="1">
<li>第一个参数都是数据框</li>
<li>随后的参数描述了使用变量名（不加引号）对数据框做什么</li>
<li>结果是一个新的数据框</li>
</ol>
<p>这些属性一起便利地将多个简单步骤串联起来得到一个复杂的操作（结果）。让我们实际来看看这些动词是怎么工作的。</p>
</section>
</section>
<section id="filter" class="level2">
<h2>使用filter()过滤行</h2>
<p><code>filter()</code>允许我们根据观测值来对数据集取子集。第一个参数是数据框的名字，第二和随后的参数是用于过滤数据框的表达式。</p>
<p>比如，我们可以选择所有一月一号的航班：</p>
<pre class="r"><code>filter(flights, month == 1, day == 1)
## # A tibble: 842 x 19
##     year month   day dep_time sched_dep_time dep_delay arr_time
##    &lt;int&gt; &lt;int&gt; &lt;int&gt;    &lt;int&gt;          &lt;int&gt;     &lt;dbl&gt;    &lt;int&gt;
##  1  2013     1     1      517            515      2.00      830
##  2  2013     1     1      533            529      4.00      850
##  3  2013     1     1      542            540      2.00      923
##  4  2013     1     1      544            545     -1.00     1004
##  5  2013     1     1      554            600     -6.00      812
##  6  2013     1     1      554            558     -4.00      740
##  7  2013     1     1      555            600     -5.00      913
##  8  2013     1     1      557            600     -3.00      709
##  9  2013     1     1      557            600     -3.00      838
## 10  2013     1     1      558            600     -2.00      753
## # ... with 832 more rows, and 12 more variables: sched_arr_time &lt;int&gt;,
## #   arr_delay &lt;dbl&gt;, carrier &lt;chr&gt;, flight &lt;int&gt;, tailnum &lt;chr&gt;,
## #   origin &lt;chr&gt;, dest &lt;chr&gt;, air_time &lt;dbl&gt;, distance &lt;dbl&gt;, hour &lt;dbl&gt;,
## #   minute &lt;dbl&gt;, time_hour &lt;dttm&gt;</code></pre>
<p>这一行代码<code>dplyr</code>执行了过滤操作并返回了一个新的数据框。<strong>dplyr从不修改输入数据，所以如果你想要保存数据，必须使用<code>&lt;-</code>进行赋值</strong>：</p>
<pre class="r"><code>jan1 &lt;- filter(flights, month == 1, day == 1)</code></pre>
<p>R要么输出结果，要么将结果保存到一个变量。如果我们想要同时做到这一点，你可以把赋值放在括号里：</p>
<pre class="r"><code>(dec25 &lt;- filter(flights, month == 12, day == 25))
## # A tibble: 719 x 19
##     year month   day dep_time sched_dep_time dep_delay arr_time
##    &lt;int&gt; &lt;int&gt; &lt;int&gt;    &lt;int&gt;          &lt;int&gt;     &lt;dbl&gt;    &lt;int&gt;
##  1  2013    12    25      456            500     -4.00      649
##  2  2013    12    25      524            515      9.00      805
##  3  2013    12    25      542            540      2.00      832
##  4  2013    12    25      546            550     -4.00     1022
##  5  2013    12    25      556            600     -4.00      730
##  6  2013    12    25      557            600     -3.00      743
##  7  2013    12    25      557            600     -3.00      818
##  8  2013    12    25      559            600     -1.00      855
##  9  2013    12    25      559            600     -1.00      849
## 10  2013    12    25      600            600      0         850
## # ... with 709 more rows, and 12 more variables: sched_arr_time &lt;int&gt;,
## #   arr_delay &lt;dbl&gt;, carrier &lt;chr&gt;, flight &lt;int&gt;, tailnum &lt;chr&gt;,
## #   origin &lt;chr&gt;, dest &lt;chr&gt;, air_time &lt;dbl&gt;, distance &lt;dbl&gt;, hour &lt;dbl&gt;,
## #   minute &lt;dbl&gt;, time_hour &lt;dttm&gt;</code></pre>
<section class="level3">
<h3>比较</h3>
<p>想要有效地过滤，你必须知道怎么利用比较操作符来选择观测值。R提供了标准的比较符：<code>&gt;</code>,<code>&gt;=</code>,<code>&lt;=</code>,<code>!=</code>和<code>==</code>。</p>
<p>如果你是初学R，一个常见的错误是用<code>=</code>而不是<code>==</code>来检测相等。如果这种情况发生了，你会收到报错信息：</p>
<pre class="r"><code>filter(flights, month = 1)
#&gt; Error: `month` (`month = 1`) must not be named, do you need `==`?</code></pre>
<p>另一个你在使用<code>==</code>时可能遭遇的常见问题是<strong>浮点数</strong>。下面的结果可能会让你惊掉大牙：</p>
<pre class="r"><code>sqrt(2) ^ 2 == 2
## [1] FALSE
1/49 * 49 == 1
## [1] FALSE</code></pre>
</section>
<section class="level3">
<h3>逻辑操作符</h3>
<p><code>&amp;</code>是与，<code>|</code>是或，<code>!</code>是非。</p>
<p>下面代码找到在十一月或十二月起飞的所有航班：</p>
<pre class="r"><code>filter(flights, month == 11 | month == 12)
## # A tibble: 55,403 x 19
##     year month   day dep_time sched_dep_time dep_delay arr_time
##    &lt;int&gt; &lt;int&gt; &lt;int&gt;    &lt;int&gt;          &lt;int&gt;     &lt;dbl&gt;    &lt;int&gt;
##  1  2013    11     1        5           2359      6.00      352
##  2  2013    11     1       35           2250    105         123
##  3  2013    11     1      455            500   -  5.00      641
##  4  2013    11     1      539            545   -  6.00      856
##  5  2013    11     1      542            545   -  3.00      831
##  6  2013    11     1      549            600   - 11.0       912
##  7  2013    11     1      550            600   - 10.0       705
##  8  2013    11     1      554            600   -  6.00      659
##  9  2013    11     1      554            600   -  6.00      826
## 10  2013    11     1      554            600   -  6.00      749
## # ... with 55,393 more rows, and 12 more variables: sched_arr_time &lt;int&gt;,
## #   arr_delay &lt;dbl&gt;, carrier &lt;chr&gt;, flight &lt;int&gt;, tailnum &lt;chr&gt;,
## #   origin &lt;chr&gt;, dest &lt;chr&gt;, air_time &lt;dbl&gt;, distance &lt;dbl&gt;, hour &lt;dbl&gt;,
## #   minute &lt;dbl&gt;, time_hour &lt;dttm&gt;</code></pre>
<p><strong>注意</strong>，你不能写成<code>filter(flights, month == 11 | 12)</code>，（虽然语义上讲的通）对于R而言，它会先计算<code>11|12</code>得到<code>1</code>，然后计算<code>month == 1</code>，这就不是我们需要的了！</p>
<p>解决这种问题的一种有用简写为<code>x %in% y</code>。这将选择符合<code>x</code>属于<code>y</code>的行（<code>x</code>是<code>y</code>中的一个值）。我们可以用它重写前面的代码：</p>
<pre class="r"><code>nov_dec &lt;- filter(flights, month %in% c(11, 12))</code></pre>
</section>
<section class="level3">
<h3>缺失值</h3>
<p><strong>NA</strong>代表未知值或者称为缺失值，它是能“传染”的，几乎任何涉及未知值的操作都会是一个未知值。</p>
<pre class="r"><code>NA &gt; 5
## [1] NA
10 == NA
## [1] NA
NA + 10
## [1] NA
NA / 2
## [1] NA</code></pre>
<p>最让人困惑的结果是这个：</p>
<pre class="r"><code>NA == NA
## [1] NA</code></pre>
<p>最简单理解为什么这是<code>TRUE</code>的方式是带入一点语境：</p>
<pre class="r"><code># 把x看作小明的年龄，我们不知道他多大
x &lt;- NA

# 把y看作小红的年龄，我们不知道她多大
y &lt;- NA

# 小明和小红一样大吗？
x == y
## [1] NA

# 我们不知道</code></pre>
<p>如果你想确定一个值是不是缺失了，使用<code>is.na()</code>：</p>
<pre class="r"><code>is.na(x)
## [1] TRUE</code></pre>
<p><code>filter()</code>仅仅会包含条件是<code>TRUE</code>的行，把是<code>FALSE</code>或者<code>NA</code>的行排除。如果你想要保留缺失值，你可以显式地指定：</p>
<pre class="r"><code>df &lt;- tibble(x = c(1, NA, 3))
filter(df, x &gt; 1)
## # A tibble: 1 x 1
##       x
##   &lt;dbl&gt;
## 1  3.00
filter(df, is.na(x) | x &gt; 1)
## # A tibble: 2 x 1
##       x
##   &lt;dbl&gt;
## 1 NA   
## 2  3.00</code></pre>
</section>
<section class="level3">
<h3>练习</h3>
<ol type="1">
<li>寻找满足以下条件的所有航班：
<ul>
<li>有一次大于等于2小时的航班抵达延误</li>
<li>飞去Houston（IAH或者HOU）</li>
<li>航空公司为United，American或者Delta （应当缩写是UA和DL）</li>
<li>在夏天起飞（July，August和September）</li>
<li>抵达延误超过两小时，但起飞时间正常</li>
<li>起飞时间在午夜到6.a.m之间（包含）</li>
</ul></li>
<li>另一个有用的<strong>dplyr</strong>过滤助手是<code>between()</code>函数。它是做什么的？你可以使用它简化用于解决前面问题的代码吗？</li>
<li>有多少航班有一个缺失的<code>dep_time</code>？其他缺失的变量有哪些？这些行表示什么呢？</li>
<li>为什么<code>NA ^ 0</code>不是缺失值？为什么<code>NA | TRUE</code>不是缺失值？为什么<code>FALSE &amp; NA</code>不是缺失值？你可以弄懂它们的基本原理吗?</li>
</ol>
<pre class="r"><code># 1
# 有一次大于等于2小时的航班抵达延误？
nrow(filter(flights, arr_delay &gt;= 120))
## [1] 10200
# 有很多抵达延误超过两小时的

# 飞去Houston（IAH或者HOU）？
nrow(filter(flights, dest %in% c(&quot;IAH&quot;, &quot;HOU&quot;)))
## [1] 9313
# 或者
nrow(filter(flights, dest == &quot;IAH&quot; | dest == &quot;HOU&quot;))
## [1] 9313

# 航空公司为United，American或者Delta （应当缩写是UA和DL）
nrow(filter(flights, carrier %in% c(&quot;UA&quot;, &quot;DL&quot;)))
## [1] 106775

# 在夏天起飞（July，August和September）
nrow(filter(flights, month &gt;=7 &amp; month &lt;=9))
## [1] 86326

# 抵达延误超过两小时，但起飞时间正常
nrow(filter(flights, dep_delay == 0, arr_delay &gt;= 120))
## [1] 3

# 起飞时间在午夜到6.a.m之间（包含）
nrow(filter(flights, hour &gt;= 0 &amp; hour &lt;= 6))
## [1] 27905

# 2
# 先查看between()函数的用法
# help(between)
# 发现它可以用来替换left &lt;= x &amp; x &lt;= right 这种情况
# 所以简化前面的结果就比较简单了
# 举个例子，比如查7到9月的航班
nrow(filter(flights, between(month, 7, 9)))
## [1] 86326

# 3
nrow(filter(flights, is.na(dep_time)))
## [1] 8255
# 所以有8000+航班缺起飞时间咯
# 接着看其他变量有缺失值没有
nrow(filter(flights, is.na(arr_time)))
## [1] 8713
nrow(filter(flights, is.na(arr_time) &amp; is.na(dep_time)))
## [1] 8255
# 有8255次起飞与降落时间都未知！！
# 我猜测可能是航班取消了吧
# 你可以谈谈你的看法，进行更多探索，在下方留。

# 4
NA ^ 0
## [1] 1
NA | TRUE
## [1] TRUE
FALSE | NA
## [1] NA
NA * 0
## [1] NA

# 就我所见，应该用类型强制转换来解释这个问题
# 在解释性编程语言（R，Python）中，当操作涉及多个数据类型时
# 语言本身会按照特定的规则进行转换。具体网上搜索。</code></pre>
</section>
</section>
<section id="arrange" class="level2">
<h2>使用arrange()排列行</h2>
<p><code>arrange()</code>函数工作原理和<code>filter()</code>相似，但它不是选择行，而是改变行的顺序。它使用一个数据框和一系列有序的列变量（或者更复杂的表达式）作为输入。如果你提供了超过一个列名，其他列对应着进行排序。</p>
<pre class="r"><code>arrange(flights, year, month, day)
## # A tibble: 336,776 x 19
##     year month   day dep_time sched_dep_time dep_delay arr_time
##    &lt;int&gt; &lt;int&gt; &lt;int&gt;    &lt;int&gt;          &lt;int&gt;     &lt;dbl&gt;    &lt;int&gt;
##  1  2013     1     1      517            515      2.00      830
##  2  2013     1     1      533            529      4.00      850
##  3  2013     1     1      542            540      2.00      923
##  4  2013     1     1      544            545     -1.00     1004
##  5  2013     1     1      554            600     -6.00      812
##  6  2013     1     1      554            558     -4.00      740
##  7  2013     1     1      555            600     -5.00      913
##  8  2013     1     1      557            600     -3.00      709
##  9  2013     1     1      557            600     -3.00      838
## 10  2013     1     1      558            600     -2.00      753
## # ... with 336,766 more rows, and 12 more variables: sched_arr_time &lt;int&gt;,
## #   arr_delay &lt;dbl&gt;, carrier &lt;chr&gt;, flight &lt;int&gt;, tailnum &lt;chr&gt;,
## #   origin &lt;chr&gt;, dest &lt;chr&gt;, air_time &lt;dbl&gt;, distance &lt;dbl&gt;, hour &lt;dbl&gt;,
## #   minute &lt;dbl&gt;, time_hour &lt;dttm&gt;</code></pre>
<p>使用<code>desc()</code>可以以逆序（降序）的方式排列：</p>
<pre class="r"><code>arrange(flights, desc(arr_delay))
## # A tibble: 336,776 x 19
##     year month   day dep_time sched_dep_time dep_delay arr_time
##    &lt;int&gt; &lt;int&gt; &lt;int&gt;    &lt;int&gt;          &lt;int&gt;     &lt;dbl&gt;    &lt;int&gt;
##  1  2013     1     9      641            900      1301     1242
##  2  2013     6    15     1432           1935      1137     1607
##  3  2013     1    10     1121           1635      1126     1239
##  4  2013     9    20     1139           1845      1014     1457
##  5  2013     7    22      845           1600      1005     1044
##  6  2013     4    10     1100           1900       960     1342
##  7  2013     3    17     2321            810       911      135
##  8  2013     7    22     2257            759       898      121
##  9  2013    12     5      756           1700       896     1058
## 10  2013     5     3     1133           2055       878     1250
## # ... with 336,766 more rows, and 12 more variables: sched_arr_time &lt;int&gt;,
## #   arr_delay &lt;dbl&gt;, carrier &lt;chr&gt;, flight &lt;int&gt;, tailnum &lt;chr&gt;,
## #   origin &lt;chr&gt;, dest &lt;chr&gt;, air_time &lt;dbl&gt;, distance &lt;dbl&gt;, hour &lt;dbl&gt;,
## #   minute &lt;dbl&gt;, time_hour &lt;dttm&gt;</code></pre>
<p>缺失值会排到最后面：</p>
<pre class="r"><code>df &lt;- tibble(x = c(5, 2, NA))
arrange(df, x)
## # A tibble: 3 x 1
##       x
##   &lt;dbl&gt;
## 1  2.00
## 2  5.00
## 3 NA
arrange(df, desc(x))
## # A tibble: 3 x 1
##       x
##   &lt;dbl&gt;
## 1  5.00
## 2  2.00
## 3 NA</code></pre>
<section id="-1" class="level3">
<h3>练习</h3>
<ol type="1">
<li>你怎么将所有的缺失值都排到最前面？（提示：使用<code>is.na()</code>）</li>
<li>给<code>flights</code>排序找到延时最多的航班；找到其中离开最早的。</li>
<li>给<code>flights</code>排序找到最快的航班。</li>
<li>哪一个航班时间最长？哪一个最短？</li>
</ol>
<pre class="r"><code># 1
arrange(df, desc(is.na(x)))
## # A tibble: 3 x 1
##       x
##   &lt;dbl&gt;
## 1 NA   
## 2  5.00
## 3  2.00
# 2
# 迟到最久
arrange(flights, desc(arr_delay))
## # A tibble: 336,776 x 19
##     year month   day dep_time sched_dep_time dep_delay arr_time
##    &lt;int&gt; &lt;int&gt; &lt;int&gt;    &lt;int&gt;          &lt;int&gt;     &lt;dbl&gt;    &lt;int&gt;
##  1  2013     1     9      641            900      1301     1242
##  2  2013     6    15     1432           1935      1137     1607
##  3  2013     1    10     1121           1635      1126     1239
##  4  2013     9    20     1139           1845      1014     1457
##  5  2013     7    22      845           1600      1005     1044
##  6  2013     4    10     1100           1900       960     1342
##  7  2013     3    17     2321            810       911      135
##  8  2013     7    22     2257            759       898      121
##  9  2013    12     5      756           1700       896     1058
## 10  2013     5     3     1133           2055       878     1250
## # ... with 336,766 more rows, and 12 more variables: sched_arr_time &lt;int&gt;,
## #   arr_delay &lt;dbl&gt;, carrier &lt;chr&gt;, flight &lt;int&gt;, tailnum &lt;chr&gt;,
## #   origin &lt;chr&gt;, dest &lt;chr&gt;, air_time &lt;dbl&gt;, distance &lt;dbl&gt;, hour &lt;dbl&gt;,
## #   minute &lt;dbl&gt;, time_hour &lt;dttm&gt;
# 出发最早
arrange(flights, dep_delay)
## # A tibble: 336,776 x 19
##     year month   day dep_time sched_dep_time dep_delay arr_time
##    &lt;int&gt; &lt;int&gt; &lt;int&gt;    &lt;int&gt;          &lt;int&gt;     &lt;dbl&gt;    &lt;int&gt;
##  1  2013    12     7     2040           2123     -43.0       40
##  2  2013     2     3     2022           2055     -33.0     2240
##  3  2013    11    10     1408           1440     -32.0     1549
##  4  2013     1    11     1900           1930     -30.0     2233
##  5  2013     1    29     1703           1730     -27.0     1947
##  6  2013     8     9      729            755     -26.0     1002
##  7  2013    10    23     1907           1932     -25.0     2143
##  8  2013     3    30     2030           2055     -25.0     2213
##  9  2013     3     2     1431           1455     -24.0     1601
## 10  2013     5     5      934            958     -24.0     1225
## # ... with 336,766 more rows, and 12 more variables: sched_arr_time &lt;int&gt;,
## #   arr_delay &lt;dbl&gt;, carrier &lt;chr&gt;, flight &lt;int&gt;, tailnum &lt;chr&gt;,
## #   origin &lt;chr&gt;, dest &lt;chr&gt;, air_time &lt;dbl&gt;, distance &lt;dbl&gt;, hour &lt;dbl&gt;,
## #   minute &lt;dbl&gt;, time_hour &lt;dttm&gt;

# 3
# 最快的航班排序
arrange(flights, air_time)
## # A tibble: 336,776 x 19
##     year month   day dep_time sched_dep_time dep_delay arr_time
##    &lt;int&gt; &lt;int&gt; &lt;int&gt;    &lt;int&gt;          &lt;int&gt;     &lt;dbl&gt;    &lt;int&gt;
##  1  2013     1    16     1355           1315     40.0      1442
##  2  2013     4    13      537            527     10.0       622
##  3  2013    12     6      922            851     31.0      1021
##  4  2013     2     3     2153           2129     24.0      2247
##  5  2013     2     5     1303           1315    -12.0      1342
##  6  2013     2    12     2123           2130    - 7.00     2211
##  7  2013     3     2     1450           1500    -10.0      1547
##  8  2013     3     8     2026           1935     51.0      2131
##  9  2013     3    18     1456           1329     87.0      1533
## 10  2013     3    19     2226           2145     41.0      2305
## # ... with 336,766 more rows, and 12 more variables: sched_arr_time &lt;int&gt;,
## #   arr_delay &lt;dbl&gt;, carrier &lt;chr&gt;, flight &lt;int&gt;, tailnum &lt;chr&gt;,
## #   origin &lt;chr&gt;, dest &lt;chr&gt;, air_time &lt;dbl&gt;, distance &lt;dbl&gt;, hour &lt;dbl&gt;,
## #   minute &lt;dbl&gt;, time_hour &lt;dttm&gt;

# 4
# 最长的航班
arrange(flights, desc(air_time))[1,]
## # A tibble: 1 x 19
##    year month   day dep_time sched_dep_time dep_delay arr_time
##   &lt;int&gt; &lt;int&gt; &lt;int&gt;    &lt;int&gt;          &lt;int&gt;     &lt;dbl&gt;    &lt;int&gt;
## 1  2013     3    17     1337           1335      2.00     1937
## # ... with 12 more variables: sched_arr_time &lt;int&gt;, arr_delay &lt;dbl&gt;,
## #   carrier &lt;chr&gt;, flight &lt;int&gt;, tailnum &lt;chr&gt;, origin &lt;chr&gt;, dest &lt;chr&gt;,
## #   air_time &lt;dbl&gt;, distance &lt;dbl&gt;, hour &lt;dbl&gt;, minute &lt;dbl&gt;,
## #   time_hour &lt;dttm&gt;
# 最快的航班
arrange(flights, air_time)[1,]
## # A tibble: 1 x 19
##    year month   day dep_time sched_dep_time dep_delay arr_time
##   &lt;int&gt; &lt;int&gt; &lt;int&gt;    &lt;int&gt;          &lt;int&gt;     &lt;dbl&gt;    &lt;int&gt;
## 1  2013     1    16     1355           1315      40.0     1442
## # ... with 12 more variables: sched_arr_time &lt;int&gt;, arr_delay &lt;dbl&gt;,
## #   carrier &lt;chr&gt;, flight &lt;int&gt;, tailnum &lt;chr&gt;, origin &lt;chr&gt;, dest &lt;chr&gt;,
## #   air_time &lt;dbl&gt;, distance &lt;dbl&gt;, hour &lt;dbl&gt;, minute &lt;dbl&gt;,
## #   time_hour &lt;dttm&gt;</code></pre>
</section>
</section>
<section id="select" class="level2">
<h2>使用select()选择列</h2>
<p>一般我们分析的原始数据集有非常多的变量（列），第一个我们要解决的问题就是缩小范围找到我们需要的数据（变量）。<code>select()</code>允许我们快速通过变量名对数据集取子集。</p>
<pre class="r"><code># 根据名字选择列
select(flights, year, month, day)
## # A tibble: 336,776 x 3
##     year month   day
##    &lt;int&gt; &lt;int&gt; &lt;int&gt;
##  1  2013     1     1
##  2  2013     1     1
##  3  2013     1     1
##  4  2013     1     1
##  5  2013     1     1
##  6  2013     1     1
##  7  2013     1     1
##  8  2013     1     1
##  9  2013     1     1
## 10  2013     1     1
## # ... with 336,766 more rows

# 选择year到day之间（包含本身）的所有列
select(flights, year:day)
## # A tibble: 336,776 x 3
##     year month   day
##    &lt;int&gt; &lt;int&gt; &lt;int&gt;
##  1  2013     1     1
##  2  2013     1     1
##  3  2013     1     1
##  4  2013     1     1
##  5  2013     1     1
##  6  2013     1     1
##  7  2013     1     1
##  8  2013     1     1
##  9  2013     1     1
## 10  2013     1     1
## # ... with 336,766 more rows

# 选择那么除year到day的所有列
select(flights, -(year:day))
## # A tibble: 336,776 x 16
##    dep_time sched_dep_time dep_delay arr_time sched_arr_time arr_delay
##       &lt;int&gt;          &lt;int&gt;     &lt;dbl&gt;    &lt;int&gt;          &lt;int&gt;     &lt;dbl&gt;
##  1      517            515      2.00      830            819     11.0 
##  2      533            529      4.00      850            830     20.0 
##  3      542            540      2.00      923            850     33.0 
##  4      544            545     -1.00     1004           1022    -18.0 
##  5      554            600     -6.00      812            837    -25.0 
##  6      554            558     -4.00      740            728     12.0 
##  7      555            600     -5.00      913            854     19.0 
##  8      557            600     -3.00      709            723    -14.0 
##  9      557            600     -3.00      838            846    - 8.00
## 10      558            600     -2.00      753            745      8.00
## # ... with 336,766 more rows, and 10 more variables: carrier &lt;chr&gt;,
## #   flight &lt;int&gt;, tailnum &lt;chr&gt;, origin &lt;chr&gt;, dest &lt;chr&gt;, air_time &lt;dbl&gt;,
## #   distance &lt;dbl&gt;, hour &lt;dbl&gt;, minute &lt;dbl&gt;, time_hour &lt;dttm&gt;</code></pre>
<p>有很多帮助函数可以使用在<code>select()</code>函数中：</p>
<ul>
<li><code>starts_with(&quot;abc&quot;)</code>匹配以“abc”开头的名字。</li>
<li><code>ends_with(&quot;xyz&quot;)</code>匹配以“xyz”结尾的名字。</li>
<li><code>contains(&quot;ijk&quot;)</code>匹配包含“ijk”的名字。</li>
<li><code>matches(&quot;(.)\\1&quot;)</code>选择符合正则表达式的变量。这里是任意包含有重复字符的变量。</li>
<li><code>num_range(&quot;x&quot;, 1:3)</code>匹配<code>x1</code>，<code>x2</code>，<code>x3</code>。</li>
</ul>
<p>运行<code>?select</code>查看更多详情。</p>
<p><code>select()</code>也可以用来重命名变量，但很少使用到，因为它会将所有未显示指定的变量删除掉。我们可以使用它的变体函数<code>rename()</code>来给变量重新命名：</p>
<pre class="r"><code>rename(flights, tail_num = tailnum)
## # A tibble: 336,776 x 19
##     year month   day dep_time sched_dep_time dep_delay arr_time
##    &lt;int&gt; &lt;int&gt; &lt;int&gt;    &lt;int&gt;          &lt;int&gt;     &lt;dbl&gt;    &lt;int&gt;
##  1  2013     1     1      517            515      2.00      830
##  2  2013     1     1      533            529      4.00      850
##  3  2013     1     1      542            540      2.00      923
##  4  2013     1     1      544            545     -1.00     1004
##  5  2013     1     1      554            600     -6.00      812
##  6  2013     1     1      554            558     -4.00      740
##  7  2013     1     1      555            600     -5.00      913
##  8  2013     1     1      557            600     -3.00      709
##  9  2013     1     1      557            600     -3.00      838
## 10  2013     1     1      558            600     -2.00      753
## # ... with 336,766 more rows, and 12 more variables: sched_arr_time &lt;int&gt;,
## #   arr_delay &lt;dbl&gt;, carrier &lt;chr&gt;, flight &lt;int&gt;, tail_num &lt;chr&gt;,
## #   origin &lt;chr&gt;, dest &lt;chr&gt;, air_time &lt;dbl&gt;, distance &lt;dbl&gt;, hour &lt;dbl&gt;,
## #   minute &lt;dbl&gt;, time_hour &lt;dttm&gt;</code></pre>
<p><code>select()</code>的另外一个操作是与<code>everything()</code>帮助函数联合使用。当你有一大堆变量你想要移动到数据框开始（最左侧）时非常有用。</p>
<pre class="r"><code>select(flights, time_hour, air_time, everything())
## # A tibble: 336,776 x 19
##    time_hour           air_time  year month   day dep_time sched_dep_time
##    &lt;dttm&gt;                 &lt;dbl&gt; &lt;int&gt; &lt;int&gt; &lt;int&gt;    &lt;int&gt;          &lt;int&gt;
##  1 2013-01-01 05:00:00    227    2013     1     1      517            515
##  2 2013-01-01 05:00:00    227    2013     1     1      533            529
##  3 2013-01-01 05:00:00    160    2013     1     1      542            540
##  4 2013-01-01 05:00:00    183    2013     1     1      544            545
##  5 2013-01-01 06:00:00    116    2013     1     1      554            600
##  6 2013-01-01 05:00:00    150    2013     1     1      554            558
##  7 2013-01-01 06:00:00    158    2013     1     1      555            600
##  8 2013-01-01 06:00:00     53.0  2013     1     1      557            600
##  9 2013-01-01 06:00:00    140    2013     1     1      557            600
## 10 2013-01-01 06:00:00    138    2013     1     1      558            600
## # ... with 336,766 more rows, and 12 more variables: dep_delay &lt;dbl&gt;,
## #   arr_time &lt;int&gt;, sched_arr_time &lt;int&gt;, arr_delay &lt;dbl&gt;, carrier &lt;chr&gt;,
## #   flight &lt;int&gt;, tailnum &lt;chr&gt;, origin &lt;chr&gt;, dest &lt;chr&gt;, distance &lt;dbl&gt;,
## #   hour &lt;dbl&gt;, minute &lt;dbl&gt;</code></pre>
<section id="-2" class="level3">
<h3>练习</h3>
<ol type="1">
<li>尽量用更多的方式从<code>flights</code>中选择<code>dep_time</code>,<code>dep_delay</code>，<code>arr_time</code>和<code>arr_delay</code>。</li>
<li>如果你多次包含同一变量名在<code>select()</code>函数里会发生什么呢？</li>
<li><code>one_of()</code>函数是用来做什么的？为什么它与下面这个向量结合使用会非常有用？</li>
</ol>
<pre><code>    var &lt;- c(
    &quot;year&quot;, &quot;month&quot;, &quot;day&quot;, &quot;dep_delay&quot;, &quot;arr_delay&quot;
    )</code></pre>
<ol start="4" type="1">
<li>下面代码的运行结果会让你吃惊吗？这个<code>select</code>的帮助函数默认是怎样处理这种情况的呢？你怎样改变默认的情况？</li>
</ol>
<pre class="r"><code># 1
# 基本select用法，使用:，使用-去除其他的，使用%in%等等

# 2
select(flights, year, year)
## # A tibble: 336,776 x 1
##     year
##    &lt;int&gt;
##  1  2013
##  2  2013
##  3  2013
##  4  2013
##  5  2013
##  6  2013
##  7  2013
##  8  2013
##  9  2013
## 10  2013
## # ... with 336,766 more rows
# 只会选择一次

# 3
# `one_of()`函数
vars &lt;- c(&quot;year&quot;, &quot;month&quot;, &quot;day&quot;, &quot;dep_delay&quot;, &quot;arr_delay&quot;)
select(flights,  one_of(vars))
## # A tibble: 336,776 x 5
##     year month   day dep_delay arr_delay
##    &lt;int&gt; &lt;int&gt; &lt;int&gt;     &lt;dbl&gt;     &lt;dbl&gt;
##  1  2013     1     1      2.00     11.0 
##  2  2013     1     1      4.00     20.0 
##  3  2013     1     1      2.00     33.0 
##  4  2013     1     1     -1.00    -18.0 
##  5  2013     1     1     -6.00    -25.0 
##  6  2013     1     1     -4.00     12.0 
##  7  2013     1     1     -5.00     19.0 
##  8  2013     1     1     -3.00    -14.0 
##  9  2013     1     1     -3.00    - 8.00
## 10  2013     1     1     -2.00      8.00
## # ... with 336,766 more rows
# 这种用法可以有效地按数据情况进行选择而不会报错

# 4
select(flights, contains(&quot;TIME&quot;))
## # A tibble: 336,776 x 6
##    dep_time sched_dep_time arr_time sched_arr_time air_time
##       &lt;int&gt;          &lt;int&gt;    &lt;int&gt;          &lt;int&gt;    &lt;dbl&gt;
##  1      517            515      830            819    227  
##  2      533            529      850            830    227  
##  3      542            540      923            850    160  
##  4      544            545     1004           1022    183  
##  5      554            600      812            837    116  
##  6      554            558      740            728    150  
##  7      555            600      913            854    158  
##  8      557            600      709            723     53.0
##  9      557            600      838            846    140  
## 10      558            600      753            745    138  
## # ... with 336,766 more rows, and 1 more variable: time_hour &lt;dttm&gt;
# 看来函数没有找到`TIME`列，所以输出了所有列
# 想要更改，我们要查看该函数的参数
args(contains)
## function (match, ignore.case = TRUE, vars = current_vars()) 
## NULL</code></pre>
</section>
</section>
<section id="mutate" class="level2">
<h2>使用mutate()添加新变量</h2>
<p>除了选择已存在的列，另一个常见的操作是添加新的列。这就是<code>mutate()</code>函数的工作了。</p>
<p><code>mutate()</code>函数通常将新增变量放在数据集的最后面。为了看到新生成的变量，我们使用一个小的数据集。</p>
<pre class="r"><code>flights_sml &lt;- select(flights,
                      year:day,
                      ends_with(&quot;delay&quot;),
                      distance,
                      air_time)

mutate(flights_sml,
       gain = arr_delay - dep_delay,
       speed = distance / air_time * 60)
## # A tibble: 336,776 x 9
##     year month   day dep_delay arr_delay distance air_time   gain speed
##    &lt;int&gt; &lt;int&gt; &lt;int&gt;     &lt;dbl&gt;     &lt;dbl&gt;    &lt;dbl&gt;    &lt;dbl&gt;  &lt;dbl&gt; &lt;dbl&gt;
##  1  2013     1     1      2.00     11.0      1400    227     9.00   370
##  2  2013     1     1      4.00     20.0      1416    227    16.0    374
##  3  2013     1     1      2.00     33.0      1089    160    31.0    408
##  4  2013     1     1     -1.00    -18.0      1576    183   -17.0    517
##  5  2013     1     1     -6.00    -25.0       762    116   -19.0    394
##  6  2013     1     1     -4.00     12.0       719    150    16.0    288
##  7  2013     1     1     -5.00     19.0      1065    158    24.0    404
##  8  2013     1     1     -3.00    -14.0       229     53.0 -11.0    259
##  9  2013     1     1     -3.00    - 8.00      944    140   - 5.00   405
## 10  2013     1     1     -2.00      8.00      733    138    10.0    319
## # ... with 336,766 more rows

mutate(flights_sml,
       gain = arr_delay - dep_delay,
       hours = air_time / 60,
       gain_per_hour = gain / hours)
## # A tibble: 336,776 x 10
##     year month   day dep_delay arr_delay distance air_time   gain hours
##    &lt;int&gt; &lt;int&gt; &lt;int&gt;     &lt;dbl&gt;     &lt;dbl&gt;    &lt;dbl&gt;    &lt;dbl&gt;  &lt;dbl&gt; &lt;dbl&gt;
##  1  2013     1     1      2.00     11.0      1400    227     9.00 3.78 
##  2  2013     1     1      4.00     20.0      1416    227    16.0  3.78 
##  3  2013     1     1      2.00     33.0      1089    160    31.0  2.67 
##  4  2013     1     1     -1.00    -18.0      1576    183   -17.0  3.05 
##  5  2013     1     1     -6.00    -25.0       762    116   -19.0  1.93 
##  6  2013     1     1     -4.00     12.0       719    150    16.0  2.50 
##  7  2013     1     1     -5.00     19.0      1065    158    24.0  2.63 
##  8  2013     1     1     -3.00    -14.0       229     53.0 -11.0  0.883
##  9  2013     1     1     -3.00    - 8.00      944    140   - 5.00 2.33 
## 10  2013     1     1     -2.00      8.00      733    138    10.0  2.30 
## # ... with 336,766 more rows, and 1 more variable: gain_per_hour &lt;dbl&gt;</code></pre>
<p>如果你仅仅想要保存新的变量，使用<code>transmute()</code>：</p>
<pre class="r"><code>transmute(flights,
          gain = arr_delay - dep_delay,
          hours = air_time / 60,
          gain_per_hour = gain / hours)
## # A tibble: 336,776 x 3
##      gain hours gain_per_hour
##     &lt;dbl&gt; &lt;dbl&gt;         &lt;dbl&gt;
##  1   9.00 3.78           2.38
##  2  16.0  3.78           4.23
##  3  31.0  2.67          11.6 
##  4 -17.0  3.05         - 5.57
##  5 -19.0  1.93         - 9.83
##  6  16.0  2.50           6.40
##  7  24.0  2.63           9.11
##  8 -11.0  0.883        -12.5 
##  9 - 5.00 2.33         - 2.14
## 10  10.0  2.30           4.35
## # ... with 336,766 more rows</code></pre>
<section class="level3">
<h3>有用的创造函数</h3>
<p>有很多函数可以结合<code>mutate()</code>一起使用来创造新的变量。这些函数的一个关键属性就是<strong>向量化</strong>的：它必须使用一组向量值作为输入，然后返回相同长度的数值作为输出。我们没有办法将所有的函数都列举出来，这里选择一些被频繁使用的函数。</p>
<p><strong>算术操作符</strong></p>
<ul>
<li>算术操作符本质都是向量化的函数，遵循“循环补齐”的规则。<strong>如果一个参数比另一个参数短，它会自动扩展为后者同样的长度</strong>。比如<code>air_time / 60</code>，<code>hours * 60</code>等等。</li>
</ul>
<p><strong>模运算</strong>（%/%和%%）</p>
<ul>
<li><code>%/%</code>整除和<code>%%</code>取余。</li>
</ul>
<p><strong>对数</strong></p>
<ul>
<li><code>log()</code>，<code>log2()</code>和<code>log10()</code></li>
</ul>
<p><strong>位移量/偏移量</strong></p>
<ul>
<li><code>lead()</code>和<code>lag()</code>允许你前移或后移变量的值。</li>
</ul>
<pre class="r"><code>(x &lt;- 1:10)
##  [1]  1  2  3  4  5  6  7  8  9 10
lag(x)
##  [1] NA  1  2  3  4  5  6  7  8  9
lead(x)
##  [1]  2  3  4  5  6  7  8  9 10 NA</code></pre>
<p><strong>累积计算</strong></p>
<ul>
<li>R提供了累积和、累积积、和累积最小值、和累积最大值：<code>cumsum()</code>,<code>cumprod()</code>,<code>cummin()</code>,<code>cummax()</code>。<code>dplyr</code>提供勒<code>cummean()</code>用于计算累积平均值。如果你想要进行滚动累积计算，可以尝试下<code>RcppRoll</code>包。</li>
</ul>
<pre class="r"><code>x
##  [1]  1  2  3  4  5  6  7  8  9 10
cumsum(x)
##  [1]  1  3  6 10 15 21 28 36 45 55
cummean(x)
##  [1] 1.0 1.5 2.0 2.5 3.0 3.5 4.0 4.5 5.0 5.5</code></pre>
<p><strong>逻辑比较</strong></p>
<ul>
<li><code>&lt;</code>,<code>&lt;=</code>,<code>&gt;</code>,<code>&gt;=</code>,<code>!=</code></li>
</ul>
<p><strong>排序rank</strong></p>
<ul>
<li>存在很多rank函数，但我们从<code>min_rank()</code>的使用开始，它可以实现最常见的rank（例如第一、第二、第三、第四），使用<code>desc()</code>进行辅助可以给最大值最小的rank。</li>
</ul>
<pre class="r"><code>y &lt;- c(1,2,2,NA,3,4)
min_rank(y)
## [1]  1  2  2 NA  4  5
min_rank(desc(y))
## [1]  5  3  3 NA  2  1</code></pre>
<p>如果<code>min_rank()</code>解决不了你的需求，看看变种<code>row_number()</code>、<code>dense_rank()</code>、<code>percent_rank()</code>、<code>cume_dist()</code>和<code>ntile()</code>，查看他们的帮助页面获取使用方法。</p>
<pre class="r"><code>row_number(y)
## [1]  1  2  3 NA  4  5
dense_rank(y)
## [1]  1  2  2 NA  3  4
percent_rank(y)
## [1] 0.00 0.25 0.25   NA 0.75 1.00
cume_dist(y)
## [1] 0.2 0.6 0.6  NA 0.8 1.0</code></pre>
</section>
</section>
<section id="summarize" class="level2">
<h2>使用summarize()计算汇总值</h2>
<p>最后一个关键的动词是<code>summarize()</code>，它将一个数据框坍缩为单个行：</p>
<pre class="r"><code>summarize(flights, delay = mean(dep_delay, na.rm = TRUE))
## # A tibble: 1 x 1
##   delay
##   &lt;dbl&gt;
## 1  12.6</code></pre>
<p>除非我们将<code>summarize()</code>与<code>group_by()</code>配对使用，不然<code>summarize()</code>显得没啥用。这个操作会将分析单元从整个数据集转到单个的组别。然后，当你使用<strong>dplyr</strong>动词对分组的数据框进行操作时，它会自动进行分组计算。比如，我们想要按日期分组，得到每个日期的平均延期：</p>
<pre class="r"><code>by_day &lt;- group_by(flights, year, month, day)
summarize(by_day, delay = mean(dep_delay, na.rm = TRUE))
## # A tibble: 365 x 4
## # Groups:   year, month [?]
##     year month   day delay
##    &lt;int&gt; &lt;int&gt; &lt;int&gt; &lt;dbl&gt;
##  1  2013     1     1 11.5 
##  2  2013     1     2 13.9 
##  3  2013     1     3 11.0 
##  4  2013     1     4  8.95
##  5  2013     1     5  5.73
##  6  2013     1     6  7.15
##  7  2013     1     7  5.42
##  8  2013     1     8  2.55
##  9  2013     1     9  2.28
## 10  2013     1    10  2.84
## # ... with 355 more rows</code></pre>
<p><code>group_by()</code>与<code>summarize()</code>的联合使用是我们最常用的dplyr工具：进行分组汇总。在我们进一步学习之前，我们需要了解一个非常强大的思想：<strong>管道</strong>。</p>
</section>
<section class="level2">
<h2>使用管道整合多个操作</h2>
<p>想象你要探索每个位置距离和平均航班延迟的关系。使用你已经知道的<code>dplyr</code>知识，你可能会写出下面的代码：</p>
<pre class="r"><code>by_dest &lt;- group_by(flights, dest)
delay &lt;- summarize(by_dest,
                   count = n(),
                   dist = mean(distance, na.rm = TRUE),
                   delay = mean(arr_delay, na.rm = TRUE) )
delay &lt;- filter(delay, count &gt; 20, dest != &quot;HNL&quot;)</code></pre>
<pre class="r"><code>ggplot(data = delay, mapping = aes(x = dist, y = delay)) +
    geom_point(aes(size=count), alpha = 1/3) + 
    geom_smooth(se = FALSE)
## `geom_smooth()` using method = &#39;loess&#39;</code></pre>
<p><img src="/post/2018/2018-03-21-data-transformation-with-dplyr_files/figure-html/unnamed-chunk-30-1.svg" width="576" /></p>
<p>看起来在大概750英里之前，距离增大，延误时间也增加；随后减少。可能是航班长了之后，飞机更有能力在空中进行调整？</p>
<p>上述代码分三步进行了数据准备：</p>
<ol type="1">
<li>按目的地将航班分组</li>
<li>汇总计算距离、平均延时和航班数目</li>
<li>移除噪声点和Honolulu航班，它太远了。</li>
</ol>
<p>这个代码写的有点令人沮丧，尽管我们不关心中间变量（临时变量），但我们却不得不创造这些中间变量存储结果数据框。命名是一件非常困难的事情，它会降低我们分析的速度。</p>
<p>另一种方式可以解决同样的问题，这就是管道pipe，<code>%&gt;</code>：</p>
<pre class="r"><code>delays &lt;- flights %&gt;%
    group_by(dest) %&gt;%
    summarize(
        count = n(),
        dist = mean(distance, na.rm = TRUE),
        delay = mean(arr_delay, na.rm = TRUE)
    ) %&gt;%
    filter(count &gt; 20, dest != &quot;HNL&quot;)
    </code></pre>
<p>这代码聚焦于转换，而不是什么被转换，这让代码更容易阅读。你可以将这段代码当作命令式的语句：分组、然后汇总，然后过滤。对<code>%&gt;%</code>理解的一种好的方式就是将它发音为”然后“。</p>
<p>在后台，<code>x %&gt;% f(y)</code>会变成<code>f(x, y)</code>，<code>x %&gt;% f(y) %&gt;% g(z)</code>会变成<code>g(f(x, y), z)</code>等等如此。你可以使用管道——用一种从上到下，从左到右的的方式重写多个操作。从现在开始我们将会频繁地用到管道，因为它会提升代码的可读性，这些我们会在后续进行深入学习。</p>
<p>使用管道进行工作是属于<strong>tidyverse</strong>的一个重要标准。唯一的例外是<strong>ggplot2</strong>，它在管道开发之前就已经写好了。不幸的是，<code>ggplot2</code>的下一个版本<code>ggvis</code>会使用管道，但还没有发布。</p>
<section id="-1" class="level3">
<h3>缺失值</h3>
<p>你可能会好奇我们先前使用的<code>na.rm</code>参数。如果我们不设置它会发生什么呢？</p>
<pre class="r"><code>flights %&gt;%
    group_by(dest) %&gt;%
    summarize(
        count = n(),
        dist = mean(distance),
        delay = mean(arr_delay)
    ) %&gt;%
    filter(count &gt; 20, dest != &quot;HNL&quot;)
## # A tibble: 96 x 4
##    dest  count  dist delay
##    &lt;chr&gt; &lt;int&gt; &lt;dbl&gt; &lt;dbl&gt;
##  1 ABQ     254  1826  4.38
##  2 ACK     265   199 NA   
##  3 ALB     439   143 NA   
##  4 ATL   17215   757 NA   
##  5 AUS    2439  1514 NA   
##  6 AVL     275   584 NA   
##  7 BDL     443   116 NA   
##  8 BGR     375   378 NA   
##  9 BHM     297   866 NA   
## 10 BNA    6333   758 NA   
## # ... with 86 more rows</code></pre>
<p><strong>我们得到了一堆缺失值！</strong>如果输入不去除缺失值，结果必然是缺失值。幸运的是，所有的聚集函数都有<code>na.rm</code>参数，它可以在计算之前移除缺失值。</p>
<pre class="r"><code>flights %&gt;%
    group_by(year, month, day) %&gt;%
    summarize(mean = mean(dep_delay, na.rm = TRUE))
## # A tibble: 365 x 4
## # Groups:   year, month [?]
##     year month   day  mean
##    &lt;int&gt; &lt;int&gt; &lt;int&gt; &lt;dbl&gt;
##  1  2013     1     1 11.5 
##  2  2013     1     2 13.9 
##  3  2013     1     3 11.0 
##  4  2013     1     4  8.95
##  5  2013     1     5  5.73
##  6  2013     1     6  7.15
##  7  2013     1     7  5.42
##  8  2013     1     8  2.55
##  9  2013     1     9  2.28
## 10  2013     1    10  2.84
## # ... with 355 more rows</code></pre>
<p>这个例子中，缺失值代表了取消的航班，所以我们解决这样问题的办法就是首先移除取消的航班。</p>
<pre class="r"><code>not_cancelled &lt;- flights %&gt;%
    filter(!is.na(dep_delay), !is.na(arr_delay))

not_cancelled %&gt;%
    group_by(year, month, day) %&gt;%
    summarize(mean = mean(dep_delay))
## # A tibble: 365 x 4
## # Groups:   year, month [?]
##     year month   day  mean
##    &lt;int&gt; &lt;int&gt; &lt;int&gt; &lt;dbl&gt;
##  1  2013     1     1 11.4 
##  2  2013     1     2 13.7 
##  3  2013     1     3 10.9 
##  4  2013     1     4  8.97
##  5  2013     1     5  5.73
##  6  2013     1     6  7.15
##  7  2013     1     7  5.42
##  8  2013     1     8  2.56
##  9  2013     1     9  2.30
## 10  2013     1    10  2.84
## # ... with 355 more rows</code></pre>
</section>
<section class="level3">
<h3>计数</h3>
<p>无论什么时候你进行汇总，包含计数<code>n()</code>或者非缺失值计数<code>sum(!is.na(x))</code>总是一个好想法。这样你可以检查你下结论来源的数据数目。例如，让我们看下有最高平均延时的飞机（根据尾号识别）：</p>
<pre class="r"><code>delays &lt;- not_cancelled %&gt;%
    group_by(tailnum) %&gt;%
    summarize(
        delay = mean(arr_delay)
    )

ggplot(data = delays, mapping = aes(x = delay)) + 
    geom_freqpoly(binwidth = 10)</code></pre>
<p><img src="/post/2018/2018-03-21-data-transformation-with-dplyr_files/figure-html/unnamed-chunk-35-1.svg" width="576" /></p>
<p>哇！居然有些飞机平均延时5个小时（300分钟）。</p>
<p>绘制平均延时下航班数目的散点图可以呈现更多的信息：</p>
<pre class="r"><code>delays &lt;- not_cancelled %&gt;%
    group_by(tailnum) %&gt;%
    summarize(
        delay = mean(arr_delay, na.rm = TRUE),
        n = n()
    )

ggplot(data = delays, mapping = aes(x = n, y = delay)) + 
    geom_point(alpha = 1/10)</code></pre>
<p><img src="/post/2018/2018-03-21-data-transformation-with-dplyr_files/figure-html/unnamed-chunk-36-1.svg" width="576" /></p>
<p>当航班数少时平均延时存在很大的变异，这并不奇怪。这个图的形状很有特征性：无论什么时候你按照组别绘制均值（或其他汇总量），你会看到变异会随着样本量的增加而减少。</p>
<p>当你看到这种类型图时，过滤掉有很少数目的组别是很有用的，可以看到数据更多的模式和更少的极端值。这正是下面代码做的事情，它同时展示了整合<code>dplyr</code>与<code>ggplot2</code>的一种手动方式。突然从<code>%&gt;%</code>转换到<code>+</code>可能会感觉有点伤，但习惯了就会感觉很便利啦：</p>
<pre class="r"><code>delays %&gt;%
    filter(n &gt; 25) %&gt;%
    ggplot(mapping = aes(x = n, y = delay)) + 
    geom_point(alpha = 1/10)</code></pre>
<p><img src="/post/2018/2018-03-21-data-transformation-with-dplyr_files/figure-html/unnamed-chunk-37-1.svg" width="576" /></p>
<p>让我们看另一个例子：棒球运动中击球手的平均表现与上场击球次数的关系。这里我们使用来自<strong>Lahman</strong>包的数据计算每个选手平均成功率（击球平均得分数，击球数/尝试数）。</p>
<p>当我画出击球手技能（用成功率衡量）与击球的机会数关系时，你会看到两种模式：</p>
<ul>
<li>数据点越多，变异越少</li>
<li>选手技能和击球机会成正相关关系。这是因为队伍可以控制谁可以上场，很显然他们都会选自己最棒的选手：</li>
</ul>
<pre class="r"><code># 转换为tibble，看起来更舒服
batting &lt;- as.tibble(Lahman::Batting)

batters &lt;- batting %&gt;%
    group_by(playerID) %&gt;%
    summarize(
        ba = sum(H, na.rm = TRUE) / sum(AB, na.rm = TRUE),
        ab = sum(AB, na.rm = TRUE)
    )

batters %&gt;% 
    filter(ab &gt; 100) %&gt;%
    ggplot(mapping = aes(x = ab, y = ba)) + 
    geom_point() +
    geom_smooth(se = FALSE)
## `geom_smooth()` using method = &#39;gam&#39;</code></pre>
<p><img src="/post/2018/2018-03-21-data-transformation-with-dplyr_files/figure-html/unnamed-chunk-38-1.svg" width="576" /></p>
</section>
<section class="level3">
<h3>有用的汇总函数</h3>
<p>仅仅使用均值、计数和求和这些函数就可以帮我做很多事情，但R提供了许多其他有用的汇总函数：</p>
<p><strong>位置度量</strong></p>
<ul>
<li>我们已经使用过<code>mean()</code>函数求取平均值（总和除以长度），<code>median()</code>函数也非常有用，它会找到中位数。</li>
</ul>
<p>有时候整合聚集函数和逻辑操作符是非常有用的：</p>
<pre class="r"><code>not_cancelled %&gt;%
    group_by(year, month, day) %&gt;% 
    summarize(
        # 平均延时
        avg_delay1 = mean(arr_delay),
        # 平均正延时
        avg_delay2 = mean(arr_delay[arr_delay &gt; 0])
    )
## # A tibble: 365 x 5
## # Groups:   year, month [?]
##     year month   day avg_delay1 avg_delay2
##    &lt;int&gt; &lt;int&gt; &lt;int&gt;      &lt;dbl&gt;      &lt;dbl&gt;
##  1  2013     1     1     12.7         32.5
##  2  2013     1     2     12.7         32.0
##  3  2013     1     3      5.73        27.7
##  4  2013     1     4    - 1.93        28.3
##  5  2013     1     5    - 1.53        22.6
##  6  2013     1     6      4.24        24.4
##  7  2013     1     7    - 4.95        27.8
##  8  2013     1     8    - 3.23        20.8
##  9  2013     1     9    - 0.264       25.6
## 10  2013     1    10    - 5.90        27.3
## # ... with 355 more rows</code></pre>
<p><strong>分布度量</strong>sd(x),IQR(x),mad(x)</p>
<ul>
<li><code>sd()</code>计算均方差（也称为标准差或简写为<code>sd</code>），是分布的标准度量；<code>IQR()</code>计算四分位数极差；<code>mad()</code>计算中位绝对离差（存在离群点时，是更稳定的<code>IQR</code>值等价物）。</li>
</ul>
<pre class="r"><code># 为何到某些目的地航班的距离比其他存在更多变异
not_cancelled %&gt;% 
    group_by(dest) %&gt;% 
    summarize(distance_sd = sd(distance)) %&gt;% 
    arrange(desc(distance_sd))
## # A tibble: 104 x 2
##    dest  distance_sd
##    &lt;chr&gt;       &lt;dbl&gt;
##  1 EGE         10.5 
##  2 SAN         10.4 
##  3 SFO         10.2 
##  4 HNL         10.0 
##  5 SEA          9.98
##  6 LAS          9.91
##  7 PDX          9.87
##  8 PHX          9.86
##  9 LAX          9.66
## 10 IND          9.46
## # ... with 94 more rows</code></pre>
<p><strong>等级度量</strong> min(x),quantile(x, 0.25),max(x)</p>
<p>分位数是中位数更通用化的一种形式。比如，<code>quantile(x, 0.25)</code>会找到<code>x</code>中刚好大于25%的值而小于7%的值的那个数。</p>
<pre class="r"><code># 每天第一班飞机和最后一般飞机是什么时候？
not_cancelled %&gt;% 
    group_by(year, month, day) %&gt;% 
    summarize(
        first = min(dep_time),
        last = max(dep_time)
    )
## # A tibble: 365 x 5
## # Groups:   year, month [?]
##     year month   day  first  last
##    &lt;int&gt; &lt;int&gt; &lt;int&gt;  &lt;dbl&gt; &lt;dbl&gt;
##  1  2013     1     1 517     2356
##  2  2013     1     2  42.0   2354
##  3  2013     1     3  32.0   2349
##  4  2013     1     4  25.0   2358
##  5  2013     1     5  14.0   2357
##  6  2013     1     6  16.0   2355
##  7  2013     1     7  49.0   2359
##  8  2013     1     8 454     2351
##  9  2013     1     9   2.00  2252
## 10  2013     1    10   3.00  2320
## # ... with 355 more rows</code></pre>
<p><strong>位置度量</strong> first(x), nth(x, 2), last(x)</p>
<p>这些函数跟<code>x[1]</code>,<code>x[2]</code>,<code>x[length(x)]</code>工作相似，但是如果该位置不存在会返回一个默认值。例如，我们想找到每天起飞的第一班和最后一班飞机：</p>
<pre class="r"><code>not_cancelled %&gt;% 
    group_by(year, month, day) %&gt;% 
    summarize(
        first_dep = first(dep_time),
        last_dep = last(dep_time)
    )
## # A tibble: 365 x 5
## # Groups:   year, month [?]
##     year month   day first_dep last_dep
##    &lt;int&gt; &lt;int&gt; &lt;int&gt;     &lt;int&gt;    &lt;int&gt;
##  1  2013     1     1       517     2356
##  2  2013     1     2        42     2354
##  3  2013     1     3        32     2349
##  4  2013     1     4        25     2358
##  5  2013     1     5        14     2357
##  6  2013     1     6        16     2355
##  7  2013     1     7        49     2359
##  8  2013     1     8       454     2351
##  9  2013     1     9         2     2252
## 10  2013     1    10         3     2320
## # ... with 355 more rows</code></pre>
<p>这些函数可以与基于rank的函数互补：</p>
<pre class="r"><code>not_cancelled %&gt;% 
    group_by(year, month, day) %&gt;% 
    mutate(r = min_rank(desc(dep_time))) %&gt;% 
    filter(r %in% range(r))
## # A tibble: 770 x 20
## # Groups:   year, month, day [365]
##     year month   day dep_time sched_dep_time dep_delay arr_time
##    &lt;int&gt; &lt;int&gt; &lt;int&gt;    &lt;int&gt;          &lt;int&gt;     &lt;dbl&gt;    &lt;int&gt;
##  1  2013     1     1      517            515      2.00      830
##  2  2013     1     1     2356           2359    - 3.00      425
##  3  2013     1     2       42           2359     43.0       518
##  4  2013     1     2     2354           2359    - 5.00      413
##  5  2013     1     3       32           2359     33.0       504
##  6  2013     1     3     2349           2359    -10.0       434
##  7  2013     1     4       25           2359     26.0       505
##  8  2013     1     4     2358           2359    - 1.00      429
##  9  2013     1     4     2358           2359    - 1.00      436
## 10  2013     1     5       14           2359     15.0       503
## # ... with 760 more rows, and 13 more variables: sched_arr_time &lt;int&gt;,
## #   arr_delay &lt;dbl&gt;, carrier &lt;chr&gt;, flight &lt;int&gt;, tailnum &lt;chr&gt;,
## #   origin &lt;chr&gt;, dest &lt;chr&gt;, air_time &lt;dbl&gt;, distance &lt;dbl&gt;, hour &lt;dbl&gt;,
## #   minute &lt;dbl&gt;, time_hour &lt;dttm&gt;, r &lt;int&gt;</code></pre>
<p><strong>计数</strong></p>
<p>你已经见过了<code>n()</code>函数，它没有任何参数并返回当前组别的大小。为了对非缺失值计数，使用<code>sum(!is.na(x))</code>。要对唯一值进行计数，使用<code>n_distinct()</code>：</p>
<pre class="r"><code># 哪个目的地有最多的carrier
not_cancelled %&gt;% 
    group_by(dest) %&gt;% 
    summarize(carriers = n_distinct(carrier)) %&gt;% 
    arrange(desc(carriers))
## # A tibble: 104 x 2
##    dest  carriers
##    &lt;chr&gt;    &lt;int&gt;
##  1 ATL          7
##  2 BOS          7
##  3 CLT          7
##  4 ORD          7
##  5 TPA          7
##  6 AUS          6
##  7 DCA          6
##  8 DTW          6
##  9 IAD          6
## 10 MSP          6
## # ... with 94 more rows</code></pre>
<p>计数十分有用，如果你仅仅想要计数，<code>dplyr</code>提供了一个帮助函数：</p>
<pre class="r"><code>not_cancelled %&gt;% 
    count(dest)
## # A tibble: 104 x 2
##    dest      n
##    &lt;chr&gt; &lt;int&gt;
##  1 ABQ     254
##  2 ACK     264
##  3 ALB     418
##  4 ANC       8
##  5 ATL   16837
##  6 AUS    2411
##  7 AVL     261
##  8 BDL     412
##  9 BGR     358
## 10 BHM     269
## # ... with 94 more rows</code></pre>
<p>你可以选择性提供一个权重变量。比如，你想用它计数（求和）一个飞机飞行的总里程：</p>
<pre class="r"><code>not_cancelled %&gt;% 
    count(tailnum, wt = distance)
## # A tibble: 4,037 x 2
##    tailnum      n
##    &lt;chr&gt;    &lt;dbl&gt;
##  1 D942DN    3418
##  2 N0EGMQ  239143
##  3 N10156  109664
##  4 N102UW   25722
##  5 N103US   24619
##  6 N104UW   24616
##  7 N10575  139903
##  8 N105UW   23618
##  9 N107US   21677
## 10 N108UW   32070
## # ... with 4,027 more rows</code></pre>
<p><strong>计数与逻辑值比例</strong> sum(x &gt; 10), mean(y == 0)</p>
<p>当与数值函数使用时，<code>TRUE</code>被转换为<code>1</code>，<code>FALSE</code>被转换为<code>0</code>。这让<code>sum()</code>与<code>mean()</code>变得非常有用，<code>sum(x)</code>可以计算<code>x</code>中<code>TRUE</code>的数目，<code>mean()</code>可以计算比例：</p>
<pre class="r"><code># 多少航班在5点前离开
not_cancelled %&gt;% 
    group_by(year, month, day) %&gt;% 
    summarize(n_early = sum(dep_time &lt; 500))
## # A tibble: 365 x 4
## # Groups:   year, month [?]
##     year month   day n_early
##    &lt;int&gt; &lt;int&gt; &lt;int&gt;   &lt;int&gt;
##  1  2013     1     1       0
##  2  2013     1     2       3
##  3  2013     1     3       4
##  4  2013     1     4       3
##  5  2013     1     5       3
##  6  2013     1     6       2
##  7  2013     1     7       2
##  8  2013     1     8       1
##  9  2013     1     9       3
## 10  2013     1    10       3
## # ... with 355 more rows


# 延时超过1小时的航班比例是多少
not_cancelled %&gt;% 
    group_by(year, month, day) %&gt;% 
    summarize(hour_perc = mean(arr_delay &gt; 60))
## # A tibble: 365 x 4
## # Groups:   year, month [?]
##     year month   day hour_perc
##    &lt;int&gt; &lt;int&gt; &lt;int&gt;     &lt;dbl&gt;
##  1  2013     1     1    0.0722
##  2  2013     1     2    0.0851
##  3  2013     1     3    0.0567
##  4  2013     1     4    0.0396
##  5  2013     1     5    0.0349
##  6  2013     1     6    0.0470
##  7  2013     1     7    0.0333
##  8  2013     1     8    0.0213
##  9  2013     1     9    0.0202
## 10  2013     1    10    0.0183
## # ... with 355 more rows</code></pre>
<section class="level4">
<h4>按多个变量分组</h4>
<p>当你按多个变量分组时，可以非常容易地对数据框汇总：</p>
<pre class="r"><code>daily &lt;- group_by(flights, year, month, day)
(per_day   &lt;- summarize(daily, flights = n()))
## # A tibble: 365 x 4
## # Groups:   year, month [?]
##     year month   day flights
##    &lt;int&gt; &lt;int&gt; &lt;int&gt;   &lt;int&gt;
##  1  2013     1     1     842
##  2  2013     1     2     943
##  3  2013     1     3     914
##  4  2013     1     4     915
##  5  2013     1     5     720
##  6  2013     1     6     832
##  7  2013     1     7     933
##  8  2013     1     8     899
##  9  2013     1     9     902
## 10  2013     1    10     932
## # ... with 355 more rows
(per_month &lt;- summarize(per_day, flights = sum(flights)))
## # A tibble: 12 x 3
## # Groups:   year [?]
##     year month flights
##    &lt;int&gt; &lt;int&gt;   &lt;int&gt;
##  1  2013     1   27004
##  2  2013     2   24951
##  3  2013     3   28834
##  4  2013     4   28330
##  5  2013     5   28796
##  6  2013     6   28243
##  7  2013     7   29425
##  8  2013     8   29327
##  9  2013     9   27574
## 10  2013    10   28889
## 11  2013    11   27268
## 12  2013    12   28135
(per_year  &lt;- summarize(per_month, flights = sum(flights)))
## # A tibble: 1 x 2
##    year flights
##   &lt;int&gt;   &lt;int&gt;
## 1  2013  336776</code></pre>
</section>
<section class="level4">
<h4>解开分组</h4>
<p>当你想要移除分组时，使用<code>ungroup()</code>函数：</p>
<pre class="r"><code>daily %&gt;%
    ungroup() %&gt;%  # 不再按日期分组
    summarize(flights = n()) # 所有的航班
## # A tibble: 1 x 1
##   flights
##     &lt;int&gt;
## 1  336776</code></pre>
</section>
</section>
<section id="mutates" class="level3">
<h3>分组的Mutates</h3>
<p>分组在与汇总衔接时非常有用，但你也可以与<code>mutate()</code>和<code>filter()</code>进行便利操作：</p>
<ul>
<li>找到每组中最糟糕的成员：</li>
</ul>
<pre class="r"><code>flights_sml %&gt;% 
    group_by(year, month, day) %&gt;% 
    filter(rank(desc(arr_delay)) &lt; 10 )
## # A tibble: 3,306 x 7
## # Groups:   year, month, day [365]
##     year month   day dep_delay arr_delay distance air_time
##    &lt;int&gt; &lt;int&gt; &lt;int&gt;     &lt;dbl&gt;     &lt;dbl&gt;    &lt;dbl&gt;    &lt;dbl&gt;
##  1  2013     1     1       853       851      184     41.0
##  2  2013     1     1       290       338     1134    213  
##  3  2013     1     1       260       263      266     46.0
##  4  2013     1     1       157       174      213     60.0
##  5  2013     1     1       216       222      708    121  
##  6  2013     1     1       255       250      589    115  
##  7  2013     1     1       285       246     1085    146  
##  8  2013     1     1       192       191      199     44.0
##  9  2013     1     1       379       456     1092    222  
## 10  2013     1     2       224       207      550     94.0
## # ... with 3,296 more rows</code></pre>
<ul>
<li>找到大于某个阈值的所有组</li>
</ul>
<pre class="r"><code>(popular_dests &lt;- flights %&gt;% 
    group_by(dest) %&gt;% 
    filter(n() &gt; 365))
## # A tibble: 332,577 x 19
## # Groups:   dest [77]
##     year month   day dep_time sched_dep_time dep_delay arr_time
##    &lt;int&gt; &lt;int&gt; &lt;int&gt;    &lt;int&gt;          &lt;int&gt;     &lt;dbl&gt;    &lt;int&gt;
##  1  2013     1     1      517            515      2.00      830
##  2  2013     1     1      533            529      4.00      850
##  3  2013     1     1      542            540      2.00      923
##  4  2013     1     1      544            545     -1.00     1004
##  5  2013     1     1      554            600     -6.00      812
##  6  2013     1     1      554            558     -4.00      740
##  7  2013     1     1      555            600     -5.00      913
##  8  2013     1     1      557            600     -3.00      709
##  9  2013     1     1      557            600     -3.00      838
## 10  2013     1     1      558            600     -2.00      753
## # ... with 332,567 more rows, and 12 more variables: sched_arr_time &lt;int&gt;,
## #   arr_delay &lt;dbl&gt;, carrier &lt;chr&gt;, flight &lt;int&gt;, tailnum &lt;chr&gt;,
## #   origin &lt;chr&gt;, dest &lt;chr&gt;, air_time &lt;dbl&gt;, distance &lt;dbl&gt;, hour &lt;dbl&gt;,
## #   minute &lt;dbl&gt;, time_hour &lt;dttm&gt;</code></pre>
<ul>
<li>标准化来计算每组的指标</li>
</ul>
<pre class="r"><code>popular_dests %&gt;% 
    filter(arr_delay &gt; 0) %&gt;% 
    mutate(prop_delay = arr_delay / sum(arr_delay)) %&gt;% 
    select(year:day, dest, arr_delay, prop_delay)
## # A tibble: 131,106 x 6
## # Groups:   dest [77]
##     year month   day dest  arr_delay prop_delay
##    &lt;int&gt; &lt;int&gt; &lt;int&gt; &lt;chr&gt;     &lt;dbl&gt;      &lt;dbl&gt;
##  1  2013     1     1 IAH       11.0   0.000111 
##  2  2013     1     1 IAH       20.0   0.000201 
##  3  2013     1     1 MIA       33.0   0.000235 
##  4  2013     1     1 ORD       12.0   0.0000424
##  5  2013     1     1 FLL       19.0   0.0000938
##  6  2013     1     1 ORD        8.00  0.0000283
##  7  2013     1     1 LAX        7.00  0.0000344
##  8  2013     1     1 DFW       31.0   0.000282 
##  9  2013     1     1 ATL       12.0   0.0000400
## 10  2013     1     1 DTW       16.0   0.000116 
## # ... with 131,096 more rows</code></pre>
<center>
（完）
</center>
</section>
</section>

</main>

  <footer>
  <script src="//yihui.name/js/math-code.js"></script>
<script async src="//cdn.bootcss.com/mathjax/2.7.1/MathJax.js?config=TeX-MML-AM_CHTML"></script>

<script async src="//yihui.name/js/center-img.js"></script>

<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');

ga('create', 'UA-108892843-2', 'auto');
ga('send', 'pageview');
</script>

<div id="disqus_thread"></div>
<script>
    var disqus_config = function () {
    
    
    
    };
    (function() {
        if (["localhost", "127.0.0.1"].indexOf(window.location.hostname) != -1) {
            document.getElementById('disqus_thread').innerHTML = 'Disqus comments not available by default when the website is previewed locally.';
            return;
        }
        var d = document, s = d.createElement('script'); s.async = true;
        s.src = '//' + "codelife" + '.disqus.com/embed.js';
        s.setAttribute('data-timestamp', +new Date());
        (d.head || d.body).appendChild(s);
    })();
</script>
<noscript>Please enable JavaScript to view the <a href="https://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript>
<a href="https://disqus.com" class="dsq-brlink">comments powered by <span class="logo-disqus">Disqus</span></a>


<script src="//cdn.bootcss.com/highlight.js/9.12.0/highlight.min.js"></script>
<script src="//cdn.bootcss.com/highlight.js/9.12.0/languages/r.min.js"></script>

<script>
hljs.configure({languages: []});
hljs.initHighlightingOnLoad();
</script>

<script type="text/javascript" src="http://w.sharethis.com/button/buttons.js"></script>
<script type="text/javascript">stLight.options({publisher: "d135f460-3fc5-4802-8169-bd08e4734a09", doNotHash: false, doNotCopy: false, hashAddressBar: false});</script>

<script type="text/javascript" src="//rf.revolvermaps.com/0/0/8.js?i=51zdev6aq4a&amp;m=0&amp;c=ff0000&amp;cr1=ffffff&amp;f=arial&amp;l=33" async="async"></script>
  
  <hr/>
  &copy; <a href="https://www.shixiangwang.top">Shixiang Wang</a> 2018 &ndash; 2018 保留所有版权 | <a href="https://github.com/ShixiangWang">Github</a> | <a href="https://twitter.com/ShixiangWang">Twitter</a> | <a href="https://www.jianshu.com/u/b6608e27dc74">简书</a>
  
  </footer>
  </body>
</html>

